#include "../../include/server/SearchEngineServer.hpp"
#include "../../include/server/TcpConnection.hpp"
#include "../../include/server/ProtocolParser.hpp"
#include "../../include/server/Logger.hpp"
#include "../../include/online/CacheManager.hpp"
#include "../../include/online/CacheGroup.hpp"
#include "../../include/online/LRUCache.hpp"
#include <iostream>
using std::endl;

extern __thread size_t __thread_id;

class MyTask
{
public:
    MyTask(const string &msg, const TcpConnectionPtr &con)
        : _msg(msg)
          , _con(con)
          , _keyRecommander()
          , _webPageSearcher()
          /* , _cacheManager(cacheManager) */
    {

    }

    void process()
    {

        //创建Cache缓存
        CacheManager *cacheManager = CacheManager::getInstance();
        ProtocolMsg msg = ProtocolMsg(_msg);
        /* cout << ">>recv msg from client: " << msg << endl; */

        /* //将消息转换成为自定义消息协议 */
        /* ProtocolMsg p(msg); */
        /* cout << "id = " << p.getMsgId() << endl; */
        /* cout << "len = " << p.getMsgLength() << endl; */
        /* cout << "contend = " << p.getMsgContend() << endl; */

        //处理业务逻辑，解析消息，判断该走哪个业务逻辑
        if(0 == msg.getMsgId())
        {
            //如果消息id为0，表示为关键字推荐
            cout << "关键字推荐业务结构" << endl;
            /* << "todo..." << endl; */
            json keyMsg = msg.getMsgContent();
            cout << keyMsg << endl;
            /* for(auto item: msg.getMsgContent()) */
            for(auto iter= keyMsg.begin();iter!= keyMsg.end();++iter)
            {
                cout<<iter.key()<<" "<<iter.value()<<endl;
                string key = iter.value();

                //判断key是否在缓存中
                string result;
                bool ret = cacheManager->getCacheGroup(__thread_id).getMainCache().isHit(key);
                if(ret)
                {
                    //缓存命中，先查缓存
                    result = cacheManager->getCacheGroup(__thread_id).getRecord(key);
                    cout << "Cache is hit!" << endl;
                }
                else
                {
                    //缓存未命中，走普通查询, 查完以后加入缓存
                    _keyRecommander=KeyRecommander(key,nullptr);
                    result=_keyRecommander.doQuery();
                    //插入缓存与同步数
                    cacheManager->getCacheGroup(0).insertRecord(key,result);
                    cacheManager->sync();
                }
                result += '\n';
                cout << result << endl;
                _con->sendInLoop(result);
            }

        }
        else if(1 == msg.getMsgId())
        {
         json keyMsg = msg.getMsgContent();
               cout << keyMsg << endl;
               /* for(auto item: msg.getMsgContent()) */
               for(auto iter= keyMsg.begin();iter!= keyMsg.end();++iter)
               {
                   cout<<iter.key()<<" "<<iter.value()<<endl;
                    string key = iter.value();
               
                
                    _webPageSearcher = WebPageSearcher(key, _con);
                    cout << "Msg from server: doQuery() starts." << endl;
                    _webPageSearcher.doQuery();
                    for(auto &elem : _webPageSearcher.jsonResult)
                    {
                        string result = elem;
                        result += '\n';
                        _con->sendInLoop(result);
                    }
               
                   /* cout << result << endl; */
                   /* _con->sendInLoop(result); */
               }
                    /* _webPageSearcher = WebPageSearcher(key, _con); */
                    /* cout << "Msg from server: doQuery() starts." << endl; */
                    /* _webPageSearcher.doQuery(); */
     
        }
    }

    ~MyTask()
    {

    }

private:
    string _msg;
    TcpConnectionPtr _con;
    KeyRecommander _keyRecommander; //关键字推荐模块
    WebPageSearcher _webPageSearcher; //网页查询模块
    CacheManager *_cacheManager;
};


//需要对_threadpool进行初始化，需要线程个数threadNum和任务队列长度queSize
//需要对_tcpserver进行初始化，需要ip和port
//_keyRecommander关联关键字
//_webPageSearcher进行网页搜索
//_protocolParser命令解析
SearchEngineServer::SearchEngineServer(size_t threadNum, size_t queSize,
                                       const string &ip, unsigned short port)
    :_threadpool(threadNum, queSize)
    ,_tcpserver(ip, port)
     ,_protocolParser()
    /* , _cacheManager(CacheManager::getInstance()) */ 
{

}

SearchEngineServer::~SearchEngineServer()
{

}

//searchEngine开始工作
//1、启动线程池
//2、？？？
void SearchEngineServer::start()
{
    //启动线程池
    _threadpool.start();

    using namespace std::placeholders;//占位符
    _tcpserver.setAllCallback(std::bind(&SearchEngineServer::onConnection, this, _1)
                              , std::bind(&SearchEngineServer::onMessage, this, _1)
                              , std::bind(&SearchEngineServer::onClose, this, _1));

    _tcpserver.start();
}

//关闭searchEngine

void SearchEngineServer::stop()
{
    //1、关闭线程池
    _threadpool.stop();

    //2、断开连接
    _tcpserver.stop();
}

void SearchEngineServer::onConnection(const TcpConnectionPtr &con)
{   
    //记录日志
    string log = con->toString() + "has connected!";
    logInfo(log);
    cout << con->toString() << " has connected!" << endl;
}

void SearchEngineServer::onMessage(const TcpConnectionPtr &con)
{
    //创建Cache缓存
    /* CacheManager *cacheManager = CacheManager::getInstance(); */
    string msg = con->receive();
    //记录日志
    string log = "服务器接收到来自客户端的消息：" + msg;
    logInfo(log);
    MyTask task(msg, con);
    _threadpool.addTask(std::bind(&MyTask::process, task));
}

void SearchEngineServer::onClose(const TcpConnectionPtr &con)
{
    //记录日志
    string log = con->toString() + "has closed!";
    logInfo(log);
    cout << con->toString() << " has closed!" << endl;
}

void SearchEngineServer::doTaskThread(const TcpConnectionPtr&, string &msg)
{

}
